home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2001 September / PC-WELT 9-2001.ISO / software / hw / brennen / flask_src.exe / Resize_old.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-06  |  24.7 KB  |  907 lines

  1. /* 
  2.  *  Resize.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24. //////////////////////////////////////////////////////////////////////
  25. //
  26. // Resize.cpp: implementation of the CResize class.
  27. //
  28. //  By
  29. //    Alberto Vigata - FlasK        version 1.0
  30. //      ultraflask@yahoo.com
  31. //            
  32. //     - YUV to RGB conversion assume YUV input image to be upside down
  33. //     - Both, YUVtoRGBA and RGBtoRGBA output RGB and RGBA images
  34. //             in the next raw sequence:     RGB images  BGR BGR BGR ...
  35. //                                            RGBA images  BGRA BGRA BGRA ...
  36. //     - Input images up to 1024x1024 pels
  37. //
  38. //////////////////////////////////////////////////////////////////////
  39.  
  40. #include "Resize.h"
  41. #include <windows.h>
  42. #include <winbase.h>
  43.  
  44.  
  45. //////////////////////////////////////////////////////////////////////
  46. //            FILTER DEFINITIONS                                      //
  47. //////////////////////////////////////////////////////////////////////
  48. #define    filter_support        (1.0)
  49. double filter(double t)
  50. {
  51.     /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
  52.     if(t < 0.0) t = -t;
  53.     if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
  54.     return(0.0);
  55. }
  56.  
  57. #define    box_support        (0.5)
  58. double box_filter(double t)
  59. {
  60.     if((t > -0.5) && (t <= 0.5)) return(1.0);
  61.     return(0.0);
  62. }
  63.  
  64. #define    triangle_support    (1.0)
  65. double triangle_filter(double t)
  66. {
  67.     if(t < 0.0) t = -t;
  68.     if(t < 1.0) return(1.0 - t);
  69.     return(0.0);
  70. }
  71.  
  72.  
  73. #define    bell_support        (1.5)
  74. double
  75. bell_filter(double t)
  76. {    /* box (*) box (*) box */
  77.     if(t < 0) t = -t;
  78.     if(t < .5) return(.75 - (t * t));
  79.     if(t < 1.5) {
  80.         t = (t - 1.5);
  81.         return(.5 * (t * t));
  82.     }
  83.     return(0.0);
  84. }
  85.  
  86.  
  87. #define    B_spline_support    (2.0)
  88. double
  89. B_spline_filter(    /* box (*) box (*) box (*) box */
  90. double t)
  91. {
  92.     double tt;
  93.  
  94.     if(t < 0) t = -t;
  95.     if(t < 1) {
  96.         tt = t * t;
  97.         return((.5 * tt * t) - tt + (2.0 / 3.0));
  98.     } else if(t < 2) {
  99.         t = 2 - t;
  100.         return((1.0 / 6.0) * (t * t * t));
  101.     }
  102.     return(0.0);
  103. }
  104.  
  105.  
  106. #define cubicConv_support (2.0)
  107. /* 
  108.  * cubicConv:
  109.  *
  110.  * Cubic convolution filter.
  111.  */
  112. double
  113. cubicConv(
  114. double t)
  115. {
  116.     double A, t2, t3;
  117.  
  118.     if(t < 0) t = -t;
  119.     t2 = t  * t;
  120.     t3 = t2 * t;
  121.  
  122.     A = -1.0;    /* user-specified free parameter */
  123.     if(t < 1.0) return((A+2)*t3 - (A+3)*t2 + 1);
  124.     if(t < 2.0) return(A*(t3 - 5*t2 + 8*t - 4));
  125.     return(0.0);
  126. }
  127.  
  128. double sinc(double x)
  129. {
  130.     x *= M_PI;
  131.     if(x != 0) return(sin(x) / x);
  132.     return(1.0);
  133. }
  134.  
  135. #define    Lanczos3_support    (3.0)
  136. double
  137. Lanczos3_filter(
  138. double t)
  139. {
  140.     if(t < 0) t = -t;
  141.     if(t < 3.0) return(sinc(t) * sinc(t/3.0));
  142.     return(0.0);
  143. }
  144.  
  145.  
  146.  
  147. #define HannWindows_support    (4.0)   /* In our case N=4 */
  148. /* 
  149.  * hann:
  150.  *
  151.  * Hann windowed sinc function. Assume N (width) = 4.
  152.  */
  153. double
  154. hann4(
  155. double t)
  156. {
  157.     int N = 4;    /* fixed filter width */
  158.  
  159.     if(t < 0) t = -t;
  160.     if(t < N) return(sinc(t) * (.5 + .5*cos(M_PI*t / N)));
  161.     return(0.0);
  162. }
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170. #define    Mitchell_support    (2.0)
  171.  
  172. #define    B    (1.0 / 3.0)
  173. #define    C    (1.0 / 3.0)
  174.  
  175. double
  176. Mitchell_filter(
  177. double t)
  178. {
  179.     double tt;
  180.  
  181.     tt = t * t;
  182.     if(t < 0) t = -t;
  183.     if(t < 1.0) {
  184.         t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
  185.            + ((-18.0 + 12.0 * B + 6.0 * C) * tt)
  186.            + (6.0 - 2 * B));
  187.         return(t / 6.0);
  188.     } else if(t < 2.0) {
  189.         t = (((-1.0 * B - 6.0 * C) * (t * tt))
  190.            + ((6.0 * B + 30.0 * C) * tt)
  191.            + ((-12.0 * B - 48.0 * C) * t)
  192.            + (8.0 * B + 24 * C));
  193.         return(t / 6.0);
  194.     }
  195.     return(0.0);
  196. }
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206. int CResize::Crop(Pixel *image, Pixel *dispImage, int xsize,int ysize,int topCrop,int bottomCrop){
  207.  
  208.     int topStart;
  209.     Pixel *imagetemp, *dispImagetemp;
  210.  
  211. if(topCrop>ysize)
  212.     topCrop=ysize;
  213. if(bottomCrop>ysize)
  214.     bottomCrop=ysize;
  215. // First byte, image bottom    
  216. ZeroMemory(dispImage    , bottomCrop*xsize*3);
  217. ZeroMemory(image,         bottomCrop*xsize*4);
  218. // bottom
  219.     topStart=ysize-topCrop;
  220.  
  221.     dispImagetemp= dispImage + topStart*xsize*3;
  222.     imagetemp = image         + topStart*xsize*4;
  223.     ZeroMemory(dispImagetemp,     topCrop*xsize*3);
  224.     ZeroMemory(imagetemp, topCrop*xsize*4);
  225.  
  226.  
  227.     return 1;
  228. }
  229.  
  230.  
  231. CResize::ResYUVtoRGBA_AR(YUVimage  *inp , Pixel  *dst,Pixel  *dispimage, bool doAR ,double iDAR){
  232.     CLIST    *contrib;        // array of contribution lists 
  233.     CLIST   *Ccontrib;        // array of contribution lists for Chroma
  234.  
  235.     int        weightY, weightU, weightV, y,x;
  236.     Pixel   *rasterU, *rasterV,*raster; /* a row or column of pixels */
  237.     Pixel   *tmp;                /* intermediate image */
  238.     Pixel   *tmpU;                /* intermediate image croma U */
  239.     Pixel   *tmpV;              /* intermediate image croma V */
  240.     Pixel   *disptemp, *dsttemp;
  241.     int     i, j, k;            /* loop variables */
  242.     int     tempxsize, tempysize, Ctempxsize, Ctempysize;
  243.      double destSAR;
  244.     int     rImageX, rImageY,yDestFirst;
  245.  
  246.     // 
  247.     if (!inp)
  248.         return 0;
  249.     if (inp->Yysize <= 0 || inp->Yysize >= 1024)
  250.         return 0;
  251.     if (inp->Cysize <= 0 || inp->Cysize >= 1024)
  252.         return 0;
  253.     if (inp->Y==NULL || inp->U==NULL || inp->V==NULL)
  254.         return 0;
  255.  
  256.     if(doAR){
  257.     //Check input DAR (display aspect ratio)
  258.         if(iDAR<=0) return 0;
  259.         if(iDAR>1) return 0;
  260.         //Working out desting Sample Aspect Ratio. Suppose ouput DAR as 3/4
  261.         destSAR=SAR( ((double)3/(double)4), oxsize, oysize);
  262.         //image dimentions
  263.         rImageX=oxsize;
  264.         rImageY= (rImageX*iDAR)/destSAR;
  265.         yDestFirst=((oysize-rImageY)/2);
  266.         if(yDestFirst<0){
  267.             yDestFirst=0;
  268.             rImageY=oysize;
  269.         }
  270.  
  271.         ZeroMemory(dispimage, oxsize*oysize*3 );
  272.         ZeroMemory(dst        , oxsize*oysize*4 );
  273.         disptemp=dispimage + (yDestFirst*oxsize*3);
  274.         dsttemp= dst       + (yDestFirst*oxsize*4);
  275.     }
  276.     else{
  277.         disptemp=dispimage;
  278.         dsttemp= dst;
  279.         rImageX=oxsize;
  280.         rImageY=oysize;
  281.     }
  282. /*    if( topCrop>=0 && topCrop<=oysize && bottomCrop>=0 && bottomCrop<=oysize)
  283.         doCrop=true;
  284.     else 
  285.         doCrop=false;*/
  286.     //IF filter=0. Nearest Neighbourgh. Direct resizing
  287.  
  288.     if(filter==0){
  289.         int yp,Cyp,xp,Cxp,Upel, Vpel, Ypel;
  290.         double stepy, stepx, Cstepy, Cstepx;
  291.         unsigned char *inputline, *Uinputline, *Vinputline;
  292.  
  293.         stepy=(double)inp->Yysize/(double)rImageY;
  294.         stepx=(double)inp->Yxsize/(double)rImageX;
  295.         Cstepy=(double)inp->Cysize/(double)rImageY;
  296.         Cstepx=(double)inp->Cxsize/(double)rImageX;
  297.         for (y=rImageY-1;y>=0;y--)
  298.         {
  299.             yp=y*stepy;
  300.             Cyp=y*Cstepy;
  301.             inputline = inp->Y + ( yp*inp->Yxsize);
  302.             Uinputline= inp->U + (Cyp*inp->Cxsize);
  303.             Vinputline= inp->V + (Cyp*inp->Cxsize);
  304.             for (x=0;x<rImageX;x++)
  305.             {
  306.  
  307. //YUV to RGB conversion with predefined color primaries crv,cgu,cbu
  308. //   Although colour primaries are predefined they should be an input
  309. //   parameter to the YUVtoRGB conversion
  310. //   MPEG2 video streams can carry different colour primaries embedded in
  311. /*    u = U - 128;
  312.       v = V - 128;
  313.       y = 76309 * (Y - 16);     //(255/219)*65536 
  314.       R = Clip[(y + crv*v + 32768)>>16];
  315.       G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
  316.       B = Clip[(y + cbu*u + 32786)>>16]; 
  317. */    
  318.                 xp=x*stepx;
  319.                 Cxp=x*Cstepx;
  320.  
  321.                 Upel = Uinputline[Cxp] - 128;
  322.                 Vpel = Vinputline[Cxp] - 128;
  323.                 Ypel = 76309*(inputline[xp]-16);
  324.                 *disptemp++= *dsttemp++ = CLAMP((Ypel + CBU*Upel + 32768)>>16);    //B
  325.                 *disptemp++= *dsttemp++ = CLAMP((Ypel - CGU*Upel - CGV*Vpel + 32768)>>16);                    //G
  326.                 *disptemp++= *dsttemp++ = CLAMP((Ypel + CRV*Vpel + 32768)>>16);                    //R
  327.                 *dsttemp++ = 0;
  328.  
  329.             }
  330.         }
  331.         return 0;
  332.     }
  333.     /* create intermediate images to hold horizontal zoom */
  334.     tmp = (Pixel *)malloc(rImageX * inp->Yysize);
  335.     tmpU= (Pixel *)malloc(rImageX * inp->Cysize);
  336.     tmpV= (Pixel *)malloc(rImageX * inp->Cysize);
  337.  
  338.     tempxsize=rImageX;
  339.     tempysize=inp->Yysize;
  340.     Ctempxsize=rImageX;
  341.     Ctempysize=inp->Cysize;
  342.  
  343.  
  344.     // pre-calculate filter contributions for a row 
  345.     // LUMINANCE CONTRIBUTIONS
  346.     contrib = AllocateContrib(rImageX);
  347.               WorkOutContributions(contrib, inp->Yxsize, rImageX);
  348.  
  349.     // CHROMA CONTRIBUTIONS
  350.     Ccontrib= AllocateContrib(rImageX);
  351.               WorkOutContributions(Ccontrib, inp->Cxsize, rImageX);
  352.  
  353. ///////////////////////////////////////////////////////////////////////
  354. //        WORKING OUT TEMPORARY X-SCALED IMAGES
  355. ///////////////////////////////////////////////////////////////////////
  356.  
  357.     /* apply filter to zoom horizontally from src to tmp */
  358.     //raster = (Pixel *)calloc(ixsize, sizeof(Pixel)*3);
  359.     /* LUMINANCE */
  360.     for(k = 0; k < tempysize; ++k) {
  361.         raster= inp->Y + k*(inp->Yxsize) ;
  362.         for(i = 0; i < tempxsize; ++i) {
  363.             weightY= 0;
  364.             for(j = 0; j < contrib[i].n; ++j) {
  365.                 weightY += raster[contrib[i].p[j].pixel]
  366.                     * contrib[i].p[j].weightShort;
  367.             }
  368.             tmp[k*(tempxsize)+i]=/* k= y pos, i= x pos */
  369.                 (Pixel)CLAMP(weightY >> 15);
  370.         }
  371.     }
  372.  
  373.  
  374.     /* CHROMA */
  375.     for(k = 0; k < Ctempysize; ++k) {
  376.         rasterU= inp->U + k*(inp->Cxsize) ;
  377.         rasterV= inp->V + k*(inp->Cxsize) ;
  378.         for(i = 0; i < Ctempxsize; ++i) {
  379.             weightU=weightV= 0;
  380.             for(j = 0; j < Ccontrib[i].n; ++j) {
  381.                 weightU += rasterU[Ccontrib[i].p[j].pixel]
  382.                     * Ccontrib[i].p[j].weightShort;
  383.                 weightV += rasterV[Ccontrib[i].p[j].pixel]
  384.                     * Ccontrib[i].p[j].weightShort;
  385.             }
  386.             tmpU[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
  387.                 (Pixel)CLAMP(weightU >> 15);
  388.             tmpV[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
  389.                 (Pixel)CLAMP(weightV >> 15);
  390.  
  391.         }
  392.     }
  393.  
  394.  
  395.  
  396.     DeAllocateContrib(contrib, rImageX);
  397.     contrib=NULL;
  398.     DeAllocateContrib(Ccontrib, rImageX);    
  399.     Ccontrib=NULL;
  400.  
  401.  
  402.  
  403.  
  404.     // pre-calculate filter contributions for a COLUMN 
  405.     // LUMINANCE CONTRIBUTIONS
  406.     contrib = AllocateContrib(rImageY);
  407.               WorkOutContributions(contrib, tempysize, rImageY);
  408.  
  409.     // CHROMA CONTRIBUTIONS
  410.     Ccontrib= AllocateContrib(rImageY);
  411.               WorkOutContributions(Ccontrib, Ctempysize, rImageY);
  412.  
  413.  
  414. ///////////////////////////////////////////////////////////////////////////
  415. //    FINAL Y-SCALING AND YUV->RGB CONVERSION
  416. ///////////////////////////////////////////////////////////////////////////    
  417.     int Ypel, Upel, Vpel,pointerA,pointerB, rowsizeA, rowsizeB, pixelChroma;
  418.     Pixel *baseY, *baseU, *baseV;
  419.     rowsizeA=rImageX*4;
  420.     rowsizeB=rImageX*3;
  421.  
  422. /////////////////////////////////////////////////////////////////////////////
  423.     for(k = 0; k < rImageX; k++) {
  424.         //pointerA=(k*4);
  425.         //pointerB=(k*3);
  426.         baseU=tmpU + k;
  427.         baseV=tmpV + k;
  428.         baseY=tmp + k;
  429.         for(i = 0; i < rImageY; i++) {
  430.             weightU=weightV=weightY = 0;
  431.             for(j = 0; j < Ccontrib[i].n; ++j) {
  432.                 pixelChroma=Ctempxsize*(Ccontrib[i].p[j].pixel);
  433.                 weightU += *( baseU + pixelChroma ) * Ccontrib[i].p[j].weightShort;
  434.                 weightV += *( baseV + pixelChroma )    * Ccontrib[i].p[j].weightShort;
  435.             }
  436.             for(j = 0; j < contrib[i].n; ++j) {
  437.                 weightY += *( baseY + tempxsize *(contrib[i].p[j].pixel))* contrib[i].p[j].weightShort;
  438.             }
  439.  
  440. // YUV to RGB conversion with predefined color primaries crv,cgu,cbu
  441. //   Although colour primaries are predefined they should be an input
  442. //   parameter to the YUVtoRGB conversion
  443. //   MPEG2 video streams can carry different colour primaries embedded in
  444. /*    u = U - 128;
  445.       v = V - 128;
  446.       y = 76309 * (Y - 16);     //(255/219)*65536 
  447.       R = Clip[(y + crv*v + 32768)>>16];
  448.       G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
  449.       B = Clip[(y + cbu*u + 32786)>>16]; 
  450. */    
  451.  
  452.             Ypel= 76309 * ( (weightY >> 15) - 16);
  453.             Upel= ((weightU>>15)-128);
  454.             Vpel= ((weightV>>15)-128);
  455.             
  456.             pointerA = (k*4) +(rImageY-1-i)*rowsizeA;
  457.             pointerB = (k*3) +(rImageY-1-i)*rowsizeB;
  458.  
  459.             dsttemp[pointerA]=
  460.             disptemp[pointerB]= //B
  461.                 (Pixel)CLAMP((Ypel + CBU*Upel + 32786)>>16);
  462.  
  463.             dsttemp[pointerA +1]=    //G
  464.             disptemp[pointerB + 1]=
  465.                 (Pixel)CLAMP((Ypel - Upel*CGU - Vpel*CGV + 32768)>>16);
  466.  
  467.             dsttemp[pointerA +2]=    //R
  468.             disptemp[pointerB + 2]=
  469.                 (Pixel)CLAMP((Ypel + Vpel*CRV + 32768)>>16);
  470.  
  471.             dsttemp[pointerA + 3]= 0;
  472.  
  473.  
  474.         }
  475.     }
  476.  
  477.     DeAllocateContrib(contrib, rImageY);
  478.     DeAllocateContrib(Ccontrib, rImageY);    
  479.     
  480.     contrib=NULL;
  481.     Ccontrib=NULL;
  482.  
  483.  
  484.     free(tmp);
  485.     free(tmpV);
  486.     free(tmpU);
  487.     return 1;
  488. }
  489.  
  490. //////////////////////////////////////////////////////////////////////
  491. // Construction/Destruction
  492. //////////////////////////////////////////////////////////////////////
  493. CResize::CResize()
  494. {
  495.  
  496. }
  497.  
  498. CResize::ResYUVtoRGBA(YUVimage  *inp , Pixel  *dst,Pixel  *dispimage){
  499.     CLIST    *contrib;        // array of contribution lists 
  500.     CLIST   *Ccontrib;        // array of contribution lists for Chroma
  501.  
  502.     int        weightY, weightU, weightV, y,x;
  503.     Pixel   *rasterU, *rasterV,*raster; /* a row or column of pixels */
  504.     Pixel   *tmp;                /* intermediate image */
  505.     Pixel   *tmpU;                /* intermediate image croma U */
  506.     Pixel   *tmpV;              /* intermediate image croma V */
  507.     int     i, j, k;            /* loop variables */
  508.     int     tempxsize, tempysize, Ctempxsize, Ctempysize;
  509.              
  510.     // 
  511.     if (!inp)
  512.         return 0;
  513.     if (inp->Yysize <= 0 || inp->Yysize >= 1024)
  514.         return 0;
  515.     if (inp->Cysize <= 0 || inp->Cysize >= 1024)
  516.         return 0;
  517.     if (inp->Y==NULL || inp->U==NULL || inp->V==NULL)
  518.         return 0;
  519.  
  520.     //IF filter=0. Nearest Neighbourgh. Direct resizing
  521.     if(filter==0){
  522.         int yp,Cyp,xp,Cxp,Upel, Vpel, Ypel;
  523.         double stepy, stepx, Cstepy, Cstepx;
  524.         unsigned char *disptemp, *dsttemp, *inputline, *Uinputline, *Vinputline;
  525.         disptemp=dispimage;
  526.         dsttemp= dst;
  527.  
  528.         stepy=(double)inp->Yysize/(double)oysize;
  529.         stepx=(double)inp->Yxsize/(double)oxsize;
  530.         Cstepy=(double)inp->Cysize/(double)oysize;
  531.         Cstepx=(double)inp->Cxsize/(double)oxsize;
  532.         for (y=oysize-1;y>=0;y--)
  533.         {
  534.             yp=y*stepy;
  535.             Cyp=y*Cstepy;
  536.             inputline = inp->Y + ( yp*inp->Yxsize);
  537.             Uinputline= inp->U + (Cyp*inp->Cxsize);
  538.             Vinputline= inp->V + (Cyp*inp->Cxsize);
  539.             for (x=0;x<oxsize;x++)
  540.             {
  541.  
  542. //YUV to RGB conversion with predefined color primaries crv,cgu,cbu
  543. //   Although colour primaries are predefined they should be an input
  544. //   parameter to the YUVtoRGB conversion
  545. //   MPEG2 video streams can carry different colour primaries embedded in
  546. /*    u = U - 128;
  547.       v = V - 128;
  548.       y = 76309 * (Y - 16);     //(255/219)*65536 
  549.       R = Clip[(y + crv*v + 32768)>>16];
  550.       G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
  551.       B = Clip[(y + cbu*u + 32786)>>16]; 
  552. */    
  553.                 xp=x*stepx;
  554.                 Cxp=x*Cstepx;
  555.  
  556.                 Upel = Uinputline[Cxp] - 128;
  557.                 Vpel = Vinputline[Cxp] - 128;
  558.                 Ypel = 76309*(inputline[xp]-16);
  559.                 *disptemp++= *dsttemp++ = CLAMP((Ypel + CBU*Upel + 32768)>>16);    //B
  560.                 *disptemp++= *dsttemp++ = CLAMP((Ypel - CGU*Upel - CGV*Vpel + 32768)>>16);                    //G
  561.                 *disptemp++= *dsttemp++ = CLAMP((Ypel + CRV*Vpel + 32768)>>16);                    //R
  562.                 *dsttemp++ = 0;
  563.  
  564.             }
  565.         }
  566.         return 0;
  567.     }
  568.     /* create intermediate images to hold horizontal zoom */
  569.     tmp = (Pixel *)malloc(oxsize * inp->Yysize);
  570.     tmpU= (Pixel *)malloc(oxsize * inp->Cysize);
  571.     tmpV= (Pixel *)malloc(oxsize * inp->Cysize);
  572.  
  573.     tempxsize=oxsize;
  574.     tempysize=inp->Yysize;
  575.     Ctempxsize=oxsize;
  576.     Ctempysize=inp->Cysize;
  577.  
  578.  
  579.     // pre-calculate filter contributions for a row 
  580.     // LUMINANCE CONTRIBUTIONS
  581.     contrib = AllocateContrib(oxsize);
  582.               WorkOutContributions(contrib, inp->Yxsize, oxsize);
  583.  
  584.     // CHROMA CONTRIBUTIONS
  585.     Ccontrib= AllocateContrib(oxsize);
  586.               WorkOutContributions(Ccontrib, inp->Cxsize, oxsize);
  587.  
  588. ///////////////////////////////////////////////////////////////////////
  589. //        WORKING OUT TEMPORARY X-SCALED IMAGES
  590. ///////////////////////////////////////////////////////////////////////
  591.  
  592.     /* apply filter to zoom horizontally from src to tmp */
  593.     //raster = (Pixel *)calloc(ixsize, sizeof(Pixel)*3);
  594.     /* LUMINANCE */
  595.     for(k = 0; k < tempysize; ++k) {
  596.         raster= inp->Y + k*(inp->Yxsize) ;
  597.         for(i = 0; i < tempxsize; ++i) {
  598.             weightY= 0;
  599.             for(j = 0; j < contrib[i].n; ++j) {
  600.                 weightY += raster[contrib[i].p[j].pixel]
  601.                     * contrib[i].p[j].weightShort;
  602.             }
  603.             tmp[k*(tempxsize)+i]=/* k= y pos, i= x pos */
  604.                 (Pixel)CLAMP(weightY >> 15);
  605.         }
  606.     }
  607.  
  608.  
  609.     /* CHROMA */
  610.     for(k = 0; k < Ctempysize; ++k) {
  611.         rasterU= inp->U + k*(inp->Cxsize) ;
  612.         rasterV= inp->V + k*(inp->Cxsize) ;
  613.         for(i = 0; i < Ctempxsize; ++i) {
  614.             weightU=weightV= 0;
  615.             for(j = 0; j < Ccontrib[i].n; ++j) {
  616.                 weightU += rasterU[Ccontrib[i].p[j].pixel]
  617.                     * Ccontrib[i].p[j].weightShort;
  618.                 weightV += rasterV[Ccontrib[i].p[j].pixel]
  619.                     * Ccontrib[i].p[j].weightShort;
  620.             }
  621.             tmpU[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
  622.                 (Pixel)CLAMP(weightU >> 15);
  623.             tmpV[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
  624.                 (Pixel)CLAMP(weightV >> 15);
  625.  
  626.         }
  627.     }
  628.  
  629.  
  630.  
  631.     DeAllocateContrib(contrib, oxsize);
  632.     contrib=NULL;
  633.     DeAllocateContrib(Ccontrib, oxsize);    
  634.     Ccontrib=NULL;
  635.  
  636.  
  637.  
  638.  
  639.     // pre-calculate filter contributions for a COLUMN 
  640.     // LUMINANCE CONTRIBUTIONS
  641.     contrib = AllocateContrib(oysize);
  642.               WorkOutContributions(contrib, tempysize, oysize);
  643.  
  644.     // CHROMA CONTRIBUTIONS
  645.     Ccontrib= AllocateContrib(oysize);
  646.               WorkOutContributions(Ccontrib, Ctempysize, oysize);
  647.  
  648.  
  649. ///////////////////////////////////////////////////////////////////////////
  650. //    FINAL Y-SCALING AND YUV->RGB CONVERSION
  651. ///////////////////////////////////////////////////////////////////////////    
  652.     int Ypel, Upel, Vpel,pointerA,pointerB, rowsizeA, rowsizeB, pixelChroma;
  653.     Pixel *baseY, *baseU, *baseV;
  654.     rowsizeA=oxsize*4;
  655.     rowsizeB=oxsize*3;
  656.  
  657. /////////////////////////////////////////////////////////////////////////////
  658.     for(k = 0; k < oxsize; k++) {
  659.         //pointerA=(k*4);
  660.         //pointerB=(k*3);
  661.         baseU=tmpU + k;
  662.         baseV=tmpV + k;
  663.         baseY=tmp + k;
  664.         for(i = 0; i < oysize; i++) {
  665.             weightU=weightV=weightY = 0;
  666.             for(j = 0; j < Ccontrib[i].n; ++j) {
  667.                 pixelChroma=Ctempxsize*(Ccontrib[i].p[j].pixel);
  668.                 weightU += *( baseU + pixelChroma ) * Ccontrib[i].p[j].weightShort;
  669.                 weightV += *( baseV + pixelChroma )    * Ccontrib[i].p[j].weightShort;
  670.             }
  671.             for(j = 0; j < contrib[i].n; ++j) {
  672.                 weightY += *( baseY + tempxsize *(contrib[i].p[j].pixel))* contrib[i].p[j].weightShort;
  673.             }
  674.  
  675. // YUV to RGB conversion with predefined color primaries crv,cgu,cbu
  676. //   Although colour primaries are predefined they should be an input
  677. //   parameter to the YUVtoRGB conversion
  678. //   MPEG2 video streams can carry different colour primaries embedded in
  679. /*    u = U - 128;
  680.       v = V - 128;
  681.       y = 76309 * (Y - 16);     //(255/219)*65536 
  682.       R = Clip[(y + crv*v + 32768)>>16];
  683.       G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
  684.       B = Clip[(y + cbu*u + 32786)>>16]; 
  685. */    
  686.  
  687.             Ypel= 76309 * ( (weightY >> 15) - 16);
  688.             Upel= ((weightU>>15)-128);
  689.             Vpel= ((weightV>>15)-128);
  690.             
  691.             pointerA = (k*4) +(oysize-1-i)*rowsizeA;
  692.             pointerB = (k*3) +(oysize-1-i)*rowsizeB;
  693.  
  694.             dst[pointerA]=
  695.             dispimage[pointerB]= //B
  696.                 (Pixel)CLAMP((Ypel + CBU*Upel + 32786)>>16);
  697.  
  698.             dst[pointerA +1]=    //G
  699.             dispimage[pointerB + 1]=
  700.                 (Pixel)CLAMP((Ypel - Upel*CGU - Vpel*CGV + 32768)>>16);
  701.  
  702.             dst[pointerA +2]=    //R
  703.             dispimage[pointerB + 2]=
  704.                 (Pixel)CLAMP((Ypel + Vpel*CRV + 32768)>>16);
  705.  
  706.             dst[pointerA + 3]= 0;
  707.  
  708.  
  709.         }
  710.     }
  711.  
  712.     DeAllocateContrib(contrib, oysize);
  713.     DeAllocateContrib(Ccontrib, oysize);    
  714.     
  715.     contrib=NULL;
  716.     Ccontrib=NULL;
  717.  
  718.  
  719.     free(tmp);
  720.     free(tmpV);
  721.     free(tmpU);
  722.     return 1;
  723. }
  724.  
  725.  
  726. CResize::ResRGBtoRGBA(Image  *src, Pixel  *dst, Pixel  *dispimage){
  727.     CLIST    *contrib;
  728.     int weightR, weightG, weightB;
  729.     int     i, j, k;            /* loop variables */
  730.     Pixel   *raster;            /* a row or column of pixels */
  731.     Pixel   *tmp;                /* intermediate image */
  732.     int     tempxsize, tempysize;
  733.     /* create intermediate image to hold horizontal zoom */
  734.     tmp = (Pixel *)malloc(oxsize * src->ysize *3);
  735.     tempxsize=oxsize;
  736.     tempysize=src->ysize;
  737.  
  738.  
  739.     /* pre-calculate filter contributions for a row */
  740.     contrib = AllocateContrib(oxsize);
  741.               WorkOutContributions(contrib, src->xsize, oxsize);
  742.  
  743.     /* apply filter to zoom horizontally from src to tmp */
  744.     for(k = 0; k < tempysize; ++k) {
  745.         raster= src->data + k*(src->xsize*3) ;
  746.         for(i = 0; i < tempxsize; ++i) {
  747.             weightR=weightG=weightB= 0;
  748.             for(j = 0; j < contrib[i].n; ++j) {
  749.                 weightR += raster[contrib[i].p[j].pixel * 3]
  750.                     * contrib[i].p[j].weightShort;
  751.                  weightG += raster[(contrib[i].p[j].pixel * 3) + 1]
  752.                     * contrib[i].p[j].weightShort;
  753.                 weightB += raster[(contrib[i].p[j].pixel * 3) + 2]
  754.                     * contrib[i].p[j].weightShort;
  755.             }
  756.             tmp[k*(tempxsize*3) +(i*3)]=/* k= y pos, i= x pos */
  757.                 (Pixel)CLAMP(weightR >> 15);
  758.             tmp[k*(tempxsize*3) +(i*3) + 1]=/* k= y pos, i= x pos */
  759.                 (Pixel)CLAMP(weightG >> 15);
  760.             tmp[k*(tempxsize*3) +(i*3) + 2]=/* k= y pos, i= x pos */
  761.                 (Pixel)CLAMP(weightB >> 15);
  762.  
  763.  
  764.             }
  765.     }
  766.  
  767.  
  768.     /* free the memory allocated for horizontal filter weights */
  769.     DeAllocateContrib(contrib, oxsize);
  770.     contrib=NULL;
  771.     
  772.  
  773.  
  774.     /* pre-calculate filter contributions for a column */
  775.     contrib = (CLIST *)calloc(oysize, sizeof(CLIST));
  776.     contrib=AllocateContrib(oysize);
  777.             WorkOutContributions(contrib, tempysize, oysize);
  778.  
  779.     /* apply filter to zoom vertically from tmp to dst */
  780.     for(k = 0; k < oxsize; ++k) {
  781.         for(i = 0; i < oysize; ++i) {
  782.             weightR=weightG=weightB= 0;
  783.             for(j = 0; j < contrib[i].n; ++j) {
  784.                 weightR += *(tmp + k*3 + tempxsize*3*(contrib[i].p[j].pixel))
  785.                     * contrib[i].p[j].weightShort;
  786.                 weightG += *(tmp + k*3 + tempxsize*3*(contrib[i].p[j].pixel) + 1)
  787.                     * contrib[i].p[j].weightShort;
  788.                 weightB += *(tmp + k*3 + tempxsize*3*(contrib[i].p[j].pixel) + 2)
  789.                     * contrib[i].p[j].weightShort;
  790.  
  791.             }
  792.             /*  DST image is in RGBA format */
  793.             /*  DISP image is in RGB format */
  794.             dispimage[i*(oxsize*3) +(k*3)]=
  795.             dst[i*(oxsize*4) +(k*4)]=/* i= y pos, k= x pos */
  796.                  (Pixel)CLAMP(weightR >> 15);
  797.             dispimage[i*(oxsize*3) +(k*3) + 1]=
  798.             dst[i*(oxsize*4) +(k*4) +1]=/* i= y pos, k= x pos */
  799.                 (Pixel)CLAMP(weightG >> 15);
  800.             dispimage[i*(oxsize*3) +(k*3) + 2]=
  801.             dst[i*(oxsize*4) +(k*4) +2]=/* i= y pos, k= x pos */
  802.                 (Pixel)CLAMP(weightB >> 15);
  803.             dst[i*(oxsize*4) +(k*4) + 3]= 0;
  804.  
  805.         }
  806.     }
  807.  
  808.  
  809.     /* free the memory allocated for vertical filter weights */
  810.     DeAllocateContrib(contrib, oysize);
  811.  
  812.     free(tmp);
  813. }
  814.  
  815.  
  816. CResize::Init(int   filter,
  817.                 int   oxsize,
  818.               int   oysize)
  819. {
  820.     CResize::filter=filter;
  821.     CResize::oxsize=oxsize;
  822.     CResize::oysize=oysize;
  823.  
  824.     /* set filter function and width */
  825.     switch( filter ) {
  826.             case '0': filterf=box_filter;            fwidth=box_support;         break;
  827.             case '1': filterf=triangle_filter;        fwidth=triangle_support;    break;
  828.             case '2': filterf=bell_filter;            fwidth=bell_support;     break;
  829.             case '3': filterf=B_spline_filter;        fwidth=B_spline_support; break;
  830.             case '5': filterf=Lanczos3_filter;        fwidth=Lanczos3_support; break;
  831.             case '6': filterf=Mitchell_filter;        fwidth=Mitchell_support;  break;
  832.             case '7': filterf=cubicConv      ;        fwidth=cubicConv_support; break;
  833.             case '8': filterf=hann4          ;        fwidth=HannWindows_support; break;
  834.             default:  filterf=cubicConv      ;        fwidth=cubicConv_support; break;
  835.             }
  836.     return 1;
  837. }
  838.  
  839. CResize::~CResize()
  840. {
  841.  
  842. }
  843.  
  844.  
  845.  
  846. CLIST* CResize::AllocateContrib(int size)
  847. {
  848.     return (CLIST *)calloc(size, sizeof(CLIST));
  849. }
  850.  
  851. CResize::DeAllocateContrib(CLIST *contrib,int size)
  852. {
  853.     int i;
  854.     for(i = 0; i < size; ++i) {
  855.         free(contrib[i].p);
  856.     }
  857.     free(contrib);
  858. }
  859.  
  860. CResize::WorkOutContributions(CLIST *contrib,int isize, int osize)
  861. {    
  862.     int i,j,k,n;
  863.     double    weightFact,scale;
  864.     double center, left, right;        
  865.     double width, fscale,  weight;    
  866.  
  867.     scale = (double)osize/(double)isize;
  868.     if(scale < 1.0){    /* If we are minimizing */
  869.         width = fwidth / scale;
  870.         fscale = 1.0 / scale;
  871.     }
  872.     else{
  873.         width = fwidth;
  874.         fscale = 1.0;
  875.     }
  876.     for(i = 0; i < osize; ++i) {
  877.             contrib[i].n = 0;
  878.             contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1), //width of filter
  879.                     sizeof(CONTRIB));
  880.             center = (double) i / scale;
  881.             left = ceil(center - width);
  882.             right = floor(center + width);
  883.             weightFact=0;
  884.             for(j = left; j <= right; ++j) {
  885.                 weight = center - (double) j;
  886.                 weight = (*filterf)(weight / fscale) / fscale;
  887.                 if(j < 0) {
  888.                     n = -j;
  889.                 } else if(j >= isize) {
  890.                     n = (isize - j) + isize - 1;
  891.                 } else {
  892.                     n = j;
  893.                 }
  894.                 k = contrib[i].n++;
  895.                 contrib[i].p[k].pixel = n;
  896.                 contrib[i].p[k].weight = weight;
  897.                 weightFact+=weight;
  898.             }
  899.             // Coefs must add up to 1 to ensure unity gain
  900.             weightFact= 1 - weightFact;
  901.             weightFact= weightFact/ contrib[i].n;
  902.             for(j=0; j<contrib[i].n; j++){
  903.                 contrib[i].p[j].weight+= weightFact;
  904.                 contrib[i].p[j].weightShort = floor(contrib[i].p[j].weight * WEIGHT_SCALE);
  905.             }
  906.     }
  907. }